<?php

abstract class AbstractDesignTimeWorkflowNode
{
  
  /**
   * @var integer
   */
  private $min_in_nodes = 1;
  
  /**
   * @var integer
   */
  private $max_in_nodes = 1;
  
  /**
   * @var integer
   */
  private $min_out_nodes = 1;
  
  /**
   * @var integer
   */
  private $max_out_nodes = 1;
  
  /**
   * @var array
   */
  protected $in_nodes = array();
  
  /**
   * @var array
   */
  protected $out_nodes = array();
  
  /**
   * @var AbstractRecipientDeterminationRule
   */
  protected $recipient;
  
  /**
   * @var string
   */
  protected $identifier;
  
  /**
   * @var MappableWorkflowContainerDecorator
   */
  protected $mapping_in = null;
  
  /**
   * @var array $actions
   */
  protected $actions = array();

  /**
   * @param string $identifier
   */
  public function __construct ($identifier)
  {
    $this->identifier = $identifier;
    $this->mapping_in = new MappableWorkflowContainerDecorator(null);
    
    $this->configure();
  }

  protected function configure ()
  {
  
  }

  /**
   * @return string
   */
  public function getIdentifier ()
  {
    return $this->identifier;
  }

  /**
   * @param AbstractDesignTimeWorkflowNode $node
   */
  public function addInNode (AbstractDesignTimeWorkflowNode $node)
  {
    // TODO add constraint checks
    $this->in_nodes[$node->getIdentifier()] = $node;
  }

  /**
   * @param AbstractDesignTimeWorkflowNode $node
   */
  public function addOutNode (AbstractDesignTimeWorkflowNode $node)
  {
    // TODO add constraint checks
    $this->out_nodes[$node->getIdentifier()] = $node;
  }

  /**
   * @return array
   */
  public function getInNodes ()
  {
    return $this->in_nodes;
  }

  /**
   * @return array
   */
  public function getOutNodes ()
  {
    return $this->out_nodes;
  }

  /**
   * @return integer
   */
  public function getMinInNodes ()
  {
    return $this->min_in_nodes;
  }

  /**
   * @return integer
   */
  public function getMinOutNodes ()
  {
    return $this->min_out_nodes;
  }

  /**
   * @return integer
   */
  public function getMaxInNodes ()
  {
    return $this->max_in_nodes;
  }

  /**
   * @return integer
   */
  public function getMaxOutNodes ()
  {
    return $this->max_out_nodes;
  }

  /**
   * @param integer $nodes
   */
  protected function setMinInNodes ($nodes)
  {
    $this->min_in_nodes = $nodes;
  }

  /**
   * @param integer $nodes
   */
  protected function setMinOutNodes ($nodes)
  {
    $this->min_out_nodes = $nodes;
  }

  /**
   * @param integer $nodes
   */
  protected function setMaxInNodes ($nodes)
  {
    $this->max_in_nodes = $nodes;
  }

  /**
   * @param integer $nodes
   */
  protected function setMaxOutNodes ($nodes)
  {
    $this->max_out_nodes = $nodes;
  }

  /**
   * @param AbstractRecipientDeterminationRule $recipient
   */
  public function setRecipient (AbstractRecipientDeterminationRule $recipient)
  {
    $this->recipient = $recipient;
  }

  /**
   * @return AbstractRecipientDeterminationRule
   */
  public function getRecipient ()
  {
    return $this->recipient;
  }

  /**
   * @return bool
   */
  public function hasRecipient ()
  {
    return ! is_null($this->recipient);
  }

  /**
   * @param RunTimeWorkflow $workflow
   * @return AbstractRunTimeWorkflowNode
   */
  abstract function createRunTimeNode (RunTimeWorkflow $workflow);

  /**
   * @return bool
   */
  public function isInteractive ()
  {
    return $this->hasRecipient();
  }

  public function mapIn ($src_key, $target_key)
  {
    $this->mapping_in->map($src_key, $target_key);
  }

  public function getMappingIn ()
  {
    return $this->mapping_in;
  }

  public function addAction (DesignTimeWorkflowNodeAction $action)
  {
    $this->actions[$action->getIdentifier()] = $action;
  }

  public function hasAction ($identifier)
  {
    return isset($this->actions[$identifier]);
  }
  
  public function hasActions() {
    return count($this->actions) > 0;
  }

  public function getActions ()
  {
    return $this->actions;
  }

  public function getAction ($identifier)
  {
    return $this->actions[$identifier];
  }

}